home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-02-15 | 4.8 KB | 123 lines | [TEXT/MPS ] |
- void DoZoomWindow (WindowPtr theWindow, short zoomDir, short hMax, short vMax)
- {
- extern EventRecord gTheEvent; // from the main event loop
- extern Boolean gHasColorQD;
-
- Rect *windRect, *zoomRect;
- Rect globalPortRect, theSect, dGDRect;
- GDHandle nthDevice, dominantGDevice;
- long sectArea, greatestArea;
-
- if (TrackBox(theWindow, gTheEvent.where, zoomDir)) {
- SetPort(theWindow);
- EraseRect(&theWindow->portRect); // recommended for cosmetic reasons
-
- if (zoomDir == inZoomOut) {
-
- /*
- * ZoomWindow() is a good basic tool, but it doesn't do everything necessary to
- * implement a good human interface when zooming. In fact it's not even close for
- * more high-end hardware configurations. We must help it along by calculating an
- * appropriate window size and location any time a window zooms out.
- */
-
- windRect = &(**((WindowPeek) theWindow)->strucRgn).rgnBBox;
- dominantGDevice = nil;
- if (gHasColorQD) {
-
- /*
- * Color QuickDraw implies the possibility of multiple monitors. This is where
- * zooming becomes more interesting. One should zoom onto the monitor containing
- * the greatest portion of the window. This requires walking the gDevice list.
- */
-
- nthDevice = GetDeviceList();
- greatestArea = 0;
- while (nthDevice != nil) {
- if (TestDeviceAttribute(nthDevice, screenDevice)) {
- if (TestDeviceAttribute(nthDevice, screenActive)) {
- SectRect(windRect, &(**nthDevice).gdRect, &theSect);
- sectArea = (long) rectWidth(theSect) * (long) rectHeight(theSect);
- if (sectArea > greatestArea) {
- greatestArea = sectArea; // save the greatest intersection
- dominantGDevice = nthDevice; // and which device it belongs to
- }
- }
- }
- nthDevice = GetNextDevice(nthDevice);
- }
- }
-
- /*
- * At this point, we know the dimensions of the window we're zooming, and we know
- * what screen we're going to put it on. To be more specific, however, we need a
- * rectangle which defines the maximum dimensions of the resized window's contents.
- * This rectangle accounts for the thickness of the window frame, the menu bar, and
- * one or two pixels around the edges for cosmetic compatibility with ZoomWindow().
- */
-
- if (dominantGDevice != nil) {
- dGDRect = (**dominantGDevice).gdRect;
- if (dominantGDevice == GetMainDevice()) // account for menu bar on main device
- dGDRect.top += GetMBarHeight();
- }
- else {
- dGDRect = qd.screenBits.bounds; // if no gDevice, use default monitor
- dGDRect.top += GetMBarHeight();
- }
-
- globalPortRect = theWindow->portRect;
- LocalToGlobal(&topLeft(globalPortRect)); // calculate the window's portRect
- LocalToGlobal(&botRight(globalPortRect)); // in global coordinates
-
- // account for the window frame and inset it a few pixels
- dGDRect.left += 2 + globalPortRect.left - windRect->left;
- dGDRect.top += 2 + globalPortRect.top - windRect->top;
- dGDRect.right -= 1 + windRect->right - globalPortRect.right;
- dGDRect.bottom -= 1 + windRect->bottom - globalPortRect.bottom;
-
- /*
- * Now we know exactly what our limits are, and since there are input parameters
- * specifying the dimensions we'd like to see, we can move and resize the zoom
- * state rectangle for the best possible results. We have three goals in this:
- * 1. Display the window entirely visible on a single device.
- * 2. Resize the window to best represent the dimensions of the document itself.
- * 3. Move the window as short a distance as possible to achieve #1 and #2.
- */
-
- zoomRect = &(**(WStateDataHandle) ((WindowPeek) theWindow)->dataHandle).stdState;
-
- /*
- * Initially set the zoom rectangle to the size requested by the input parameters,
- * although not smaller than a minimum size. We do this without moving the origin.
- */
-
- zoomRect->right = (zoomRect->left = globalPortRect.left) +
- max(hMax, MinWindowWidth(theWindow));
- zoomRect->bottom = (zoomRect->top = globalPortRect.top) +
- max(vMax, MinWindowHeight(theWindow));
-
- // Shift the entire rectangle if necessary to bring its origin inside dGDRect.
- OffsetRect(zoomRect,
- max(dGDRect.left - zoomRect->left, 0),
- max(dGDRect.top - zoomRect->top, 0));
-
- /*
- * Shift the rectangle up and/or to the left if necessary to accomodate the view,
- * and if it is possible to do so. The rectangle may not be moved such that its
- * origin would fall outside of dGDRect.
- */
-
- OffsetRect(zoomRect,
- -pin(zoomRect->right - dGDRect.right, 0, zoomRect->left - dGDRect.left),
- -pin(zoomRect->bottom - dGDRect.bottom, 0, zoomRect->top - dGDRect.top));
-
- // Clip expansion to dGDRect, in case view is larger than dGDRect.
- zoomRect->right = min(zoomRect->right, dGDRect.right);
- zoomRect->bottom = min(zoomRect->bottom, dGDRect.bottom);
- }
-
- ZoomWindow(theWindow, zoomDir, false); // all it needed was a brain transplant
- }
- }
-